package com.fcscs.cservice.service.impl;

import java.io.InputStream;
import java.io.Serializable;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.fcscs.core.common.ErrorEnums;
import com.fcscs.core.service.FcsManager;
import com.fcscs.cservice.common.CServiceCommonEnums.BookingStatus;
import com.fcscs.cservice.common.CServiceCommonEnums.BookingViewOrderBy;
import com.fcscs.cservice.common.CServiceCommonEnums.CommAdaptorEnum;
import com.fcscs.cservice.common.CServiceCommonEnums.GuestProfileType;
import com.fcscs.cservice.common.CServiceCommonEnums.NotifType;
import com.fcscs.cservice.common.CServiceCommonEnums.NotifyType;
import com.fcscs.cservice.communication.CommIntfAdaptor;
import com.fcscs.cservice.communication.OutboundHandler;
import com.fcscs.cservice.dao.BookingDao;
import com.fcscs.cservice.dao.ReservationDao;
import com.fcscs.cservice.dao.RestaurantDao;
import com.fcscs.cservice.domain.BookingBase;
import com.fcscs.cservice.domain.Country;
import com.fcscs.cservice.domain.PropertyConfigRestaurant;
import com.fcscs.cservice.domain.model.BookingIdAndMessage;
import com.fcscs.cservice.domain.model.BookingIdAndStatus;
import com.fcscs.cservice.domain.model.BookingUpdate;
import com.fcscs.cservice.domain.model.BookingView;
import com.fcscs.cservice.domain.model.NonInHouseGuestProfile;
import com.fcscs.cservice.domain.model.ReservationView;
import com.fcscs.cservice.domain.validator.BookingServiceValidators;
import com.fcscs.cservice.service.BookingManager;
import com.ibm.icu.text.SimpleDateFormat;

@Service("bookingManager")
public class BookingManagerImpl extends FcsManager implements BookingManager {

	@Autowired
	private BookingDao bkDao;
	
	@Autowired
	private ReservationDao reserDao;
	
	@Autowired
	private RestaurantDao restDao;
	
	@Autowired
	OutboundHandler outHdl;
	
	private static Logger LOGGER = Logger.getLogger(BookingManagerImpl.class);

	@Override
	public <E extends BookingBase> E get(Class<E> cls, long id) {
		return bkDao.get(cls, id);
	}

	@Override
	public BookingBase get(long id) {
		return bkDao.get(id);
	}

	@Override
	public Boolean delete(BookingBase loc) {
		return bkDao.delete(loc);
	}

	@Override
	public void permDelete(BookingBase loc) {
		bkDao.permDelete(loc);
	}

	@Override
	public <E extends BookingBase> E save(E loc) {
		//*******************************************
		ErrorEnums err = new BookingServiceValidators.BookingBaseValidator().validate(loc, loc.getId() == null);
		if (err != null) {
			LOGGER.debug(err);
			return null;
		}
		loc.setOrgId(ManagerContextValueUtil.getOrgId());
		loc.setCreatedBy(ManagerContextValueUtil.getUserId());
		return bkDao.save(loc);
	}

	@Override
	public List<BookingView> simFindBookings(Long propId,
			Long restaurantId, String term,Date reservationDate, int start, int resultCnt) {
		return bkDao.simFindBookings(ManagerContextValueUtil.getOrgId(), propId, restaurantId, term,reservationDate, start, resultCnt);
	}

	@Override
	public int simFindBookingsCnt( Long propId, Long restaurantId,String term,Date reservationDate) {
		return bkDao.simFindBookingsCnt(ManagerContextValueUtil.getOrgId(), propId, restaurantId, term ,reservationDate);
	}

	@Override
	public List<BookingView> findBookings( Long propId, Long restaurantId, String term, String firstName,
			String lastName, String mobileNo,GuestProfileType guestType, Date reservationDate, List<BookingStatus> statuses,
			Date startDate,Date endDate,int start,int resultCnt, BookingViewOrderBy orderBy, boolean sortDesc) {
		return bkDao.findBookings(ManagerContextValueUtil.getOrgId(), propId, restaurantId, term, firstName, lastName, mobileNo,guestType, reservationDate,
				statuses,startDate,endDate,start, resultCnt, orderBy, sortDesc);
	}

	@Override
	public int findBookingsCnt( Long propId, Long restaurantId, String term, String firstName,
			String lastName, String mobileNo, GuestProfileType guestType, Date reservationDate, List<BookingStatus> statuses,Date startDate,Date endDate) {
		return bkDao.findBookingsCnt(ManagerContextValueUtil.getOrgId(), propId, restaurantId, term, firstName, lastName, mobileNo, guestType, reservationDate,
				statuses,startDate,endDate);
	}


	@Override
	public List<BookingIdAndMessage> updateBookingStatus( Long propId,List<BookingIdAndStatus> idstatus) {
		List<BookingIdAndMessage> list = bkDao.updateBookingStatus(ManagerContextValueUtil.getOrgId(), propId, ManagerContextValueUtil.getUserId(), idstatus);
		return list;
	}

	@Override
	public int getBookingHistoryCnt( Long propId, long guestId) {
		int count = bkDao.getBookingHistoryCnt(ManagerContextValueUtil.getOrgId(),propId, guestId);
		return count;
	}

	@Override
	public List<BookingView> getBookingHistory( Long propId, long guestId,int start, int resultCnt) {
		List<BookingView> list = bkDao.getBookingHistory(ManagerContextValueUtil.getOrgId(),propId, guestId, start, resultCnt);
		return list;
	}

	@Override
	public BookingView createBooking(BookingBase bkBase,NonInHouseGuestProfile nonInGuest) {
		//*************************
		ErrorEnums err = new BookingServiceValidators.CreateBookingValidator().validate(bkBase, nonInGuest);
		if (err != null) {
			LOGGER.debug(err);
			return null;
		}
		bkBase.setCreatedBy(ManagerContextValueUtil.getUserId());
		ReservationView rv = reserDao.getCurReservationViewByGP(bkBase.getGuestProfileId());
		if (rv != null) {
			bkBase.setReservationId(rv.getReservationViewId());
			bkBase.setArrivalDate(rv.getArrivalDateTime());
			bkBase.setDepartureDate(rv.getDepartureDateTime());
		}
		BookingView bookingView = bkDao.createBooking(bkBase, nonInGuest);
		return bookingView;
	}

	@Override
	public BookingView updateBooking(BookingUpdate bookingUpdate) {
		//****************************
		if(bookingUpdate.getBookingId() <=0 || bookingUpdate.getGuestId() <=0){
			LOGGER.debug(ErrorEnums.GeneralError.REQURIED_FLD_MISSING);
			return null;
		}
		bookingUpdate.setOrgId(ManagerContextValueUtil.getOrgId());
		bookingUpdate.setUpdatedBy(ManagerContextValueUtil.getUserId());
		BookingView bookingView = bkDao.updateBooking(bookingUpdate);
		
		//Add send Message
		if(bookingView.getStatus().equals(BookingStatus.BOOKED.toString())){
			for(String s : bookingView.getNotify().split("\\|")){
				if(s.equals(NotifyType.EMAIL.toString())){
					sendMessageToGuest(bookingView);
					//Add Send SMS
				}
			}
		}
		return bookingView;
	}

	private void sendMessageToGuest(BookingView bookingView) {
		long orgId = bookingView.getOrgId();
		Long propId = bookingView.getPropertyId();
		SimpleDateFormat sp = new SimpleDateFormat("yyyy-MM-dd");
		SimpleDateFormat sp1 = new SimpleDateFormat("HH:mm");
		PropertyConfigRestaurant pcr = restDao.getPropertyConfigRestaurant(orgId, propId);
		String title = pcr.getBookingConfirmTitle().
						replace("<[<RESTAURANT>]>", bookingView.getRestaurantName());
		String content = pcr.getBookingConfirmBody().
						replace("<[<DATE>]>",sp.format(bookingView.getReservationDate())).
						replace("<[<TIME>]>",sp1.format(bookingView.getReservationDate()));
		Map<CommIntfAdaptor.CommParam, Serializable> params = new HashMap<CommIntfAdaptor.CommParam, Serializable>();
		params.put(CommIntfAdaptor.CommParam.DEVICE, bookingView.getEmail());
		params.put(CommIntfAdaptor.CommParam.TITLE, title);
		params.put(CommIntfAdaptor.CommParam.FONT_SIZE, CommIntfAdaptor.DEFAULT_FONT_SIZE);
		params.put(CommIntfAdaptor.CommParam.MSG_TYPE, NotifType.BILL_NOTIF.toString());
		params.put(CommIntfAdaptor.CommParam.PROP_IP,"");
		sendMessage("",CommAdaptorEnum.EMAIL,"",content.getBytes(),params);
	}

	private boolean sendMessage(String ip,CommAdaptorEnum type,String description,
									byte[] data,Map<CommIntfAdaptor.CommParam, Serializable> parames){
		byte[] be= outHdl.sendBytes(ip,type, description, data, parames);
		if(be != null){
			return true;
		}
		return false;
	}
	
	@Override
	public List<Country> seedCountry(Long propId,String path) {
		long orgId = ManagerContextValueUtil.getOrgId();
		if(orgId == 0L){
			return null;
		}
		if(propId != ManagerContextValueUtil.getPropId()){
			propId = ManagerContextValueUtil.getPropId();
		}
		List<Country> list = bkDao.seedCountry(orgId,propId,path);
		return list;
	}

	@Override
	public InputStream readImageFromDataBase() {
		return bkDao.readImageFromDataBase();
	}
}
